----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    14:50:34 11/29/2011 
-- Design Name: 
-- Module Name:    INTH - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.all;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity INTH is
	port(
			RegIH : in std_ulogic_vector(15 downto 0);
			int_clk : in std_ulogic;
			int_ext : in std_ulogic;
			iINS : in  std_ulogic_vector(15 downto 0);
			oINS : out std_ulogic_vector(15 downto 0);
			iPC1 : in  std_ulogic_vector(15 downto 0);
			iPC2 : in  std_ulogic_vector(15 downto 0);
			oPC  : out std_ulogic_vector(15 downto 0);
			iRPC_enable : in  std_ulogic;
			oRPC_enable : out std_ulogic;
			enable : in std_ulogic;
			rst : in std_ulogic;
			clk : in std_ulogic
		);
end INTH;

architecture Behavioral of INTH is
	type enum_state is (
		normal_state,
		int1_state,
		int2_state,
		int3_state,
		int4_state
	);
	signal INT_state : enum_state;
	--signal INT_INS   : std_ulogic_vector(15 downto 0);
	signal INT_NUM   : std_ulogic_vector(7 downto 0);
	
	signal one : std_ulogic_vector(15 downto 0):=x"0001";
begin

	process(clk,rst,enable,iINS,int_clk,int_ext,RegIH) -- change state
	--input:  clk, rst, enable, INT_state, iINS
	--output: INT_state, INT_INS
	begin
		if(rst='0')then
			INT_state <= normal_state;
		else
			if(enable='1' and rising_edge(clk))then
				case INT_state is
					when normal_state =>
						if(RegIH(15)='1')then
							if(int_clk='1')then
								INT_state <= int1_state;
								INT_NUM <= x"20";
							elsif(int_ext='1')then
								INT_state <= int1_state;
								INT_NUM <= x"10";
							elsif(iINS(15 downto 8)=x"F8")then
								INT_state <= int1_state;
								INT_NUM <= "0000" & iINS(3 downto 0);
							end if;
						end if;
					when int1_state =>
						INT_state <= int2_state;
					when int2_state =>
						INT_state <= int3_state;
					when int3_state =>
						INT_state <= int4_state;
					--	INT_state <= normal_state;
					when int4_state =>
						INT_state <= normal_state;
					when others=>
						INT_state <= normal_state;
				end case;
			end if;
		end if;
	end process;
	
	process(INT_state,INT_NUM,enable,iRPC_enable,iINS)
	--input: INT_state, INT_NUM, enable, iRPC_enable, iINS
	--output: oINS, oRPC_enable
	begin
		if((INT_state=normal_state or INT_state=int4_state) and iRPC_enable='1')then
		--if(INT_state=normal_state and iRPC_enable='1')then
			oRPC_enable <= '1';
		else
			oRPC_enable <= '0';
		end if;
		case INT_state is
			when normal_state =>
				oINS <= iINS;
			when int1_state =>
				oINS <= "0001100100011111"; --int1
			when int2_state =>
				oINS <= "00011010"&INT_NUM; --int2
			when int3_state =>
				oINS <= "0001110011111111"; --int3
			when int4_state =>
				oINS <= x"0800"; --nop
			when others=>
				oINS <= iINS;
		end case;
	end process;


	process(iPC1,iPC2,INT_state,INT_NUM)
	begin
		if (INT_state /= normal_state)and(INT_state /= int4_state)and(INT_NUM/=x"00") then
			oPC<=std_ulogic_vector(unsigned(iPC1)-unsigned(one));
		else
			oPC<=iPC2;
		end if;
	end process;
	
end Behavioral;

